/**
 * 描述：数组的底层实现
 *
 * @author WangB
 * @create 2018-10-20-0:26
 */
public class Array<E> {
    private E[] data;
    private int size;//用来维护数组中有多少实际元素。

    /**
     * 构造函数初始化函数
     *
     * @param capacity 数组容量
     */
    public Array ( int capacity ) {
        data = ( E[] ) new Object[ capacity ];//需要先new一个Object，然后强制类型转换
        size = 0;
    }

    /**
     * 默认的构造函数，无参数的构造函数
     */
    public Array ( ) {
        this ( 10 );//是编译器提供的提示信息
    }

    /**
     * @return 数组当前的数据个数
     */
    public int getSize ( ) {
        return size;
    }

    /**
     * @return 获取数组的长度。
     */
    public int getCapacity ( ) {
        return data.length;
    }

    /**
     * @return 返回数组是否为空
     */
    public boolean isEmpty ( ) {
        return size == 0;
    }

    /**
     * 向数组中末尾添加元素
     *
     * @param e
     */
    public void addLast ( E e ) {

        //可以直接调用add了
        add ( size , e );
        /**
         if(size==data.length)
         throw new IllegalArgumentException("Array is full");

         data[size] = e ;
         size++;
         **/
    }

    /**
     * 在index的位置添加一个新元素e
     *
     * @param index
     * @param e
     */
    public void add ( int index , E e ) {
        if ( index < 0 || index > size )
            throw new IllegalArgumentException ( "Add failed,Require index >=0 ,index <= size" );

        //如果已经满了，使用扩容技术
        if ( size == data.length )
            //throw new IllegalArgumentException("Array is full");
            resize ( 2 * data.length );


        for ( int i = size - 1 ; i >= index ; i-- ) {
            data[ i + 1 ] = data[ i ];
        }
        data[ index ] = e;
        size++;
    }

    /**
     * 在数组前面添加一个index
     *
     * @param e
     */
    public void addFirst ( E e ) {
        add ( 0 , e );
    }

    /**
     * 查询数组中是否包括一个元素
     *
     * @param e
     * @return
     */
    public boolean contains ( E e ) {
        for ( int i = 0 ; i < size ; i++ ) {
            if ( data[ i ].equals ( e ) )
                return true;
        }
        return false;
    }

    /**
     * 查询数组中e所在的位置，不存在的话返回-1
     *
     * @param e
     * @return
     */
    public int find ( E e ) {
        for ( int i = 0 ; i < size ; i++ ) {
            if ( data[ i ].equals ( e ) )
                return i;
        }
        return -1;
    }

    /**
     * 在数组中删除index中的元素，并且返回
     *
     * @param index
     * @return
     */
    public E remove ( int index ) {
        if ( index < 0 || index >= size )
            throw new IllegalArgumentException ( "remove failed index is illegal" );
        E ret = data[ index ];
        for ( int i = index + 1 ; i < size ; i++ ) {
            data[ i - 1 ] = data[ i ];
        }
        size--;
        //如果实际元素等于容量的1/4，就缩容
        if ( size == data.length / 4 && data.length / 2 != 0 )
            resize ( data.length / 2 );
        return ret;
    }

    /**
     * 从数组中删除第一个元素
     *
     * @return
     */
    public E removeFirst ( ) {
        return remove ( 0 );
    }

    /**
     * 从数组中删除最后一个元素
     *
     * @return
     */
    public E removeLast ( ) {
        return remove ( size - 1 );
    }

    /**
     * 从数组中删除指定的元素
     *
     * @param e
     */
    public void removeElement ( E e ) {
        int index = find ( e );
        if ( index != -1 )
            remove ( index );

    }

    @Override //覆盖父类object的toString方法。使用这个标识符可以完成纠错功能
    public String toString ( ) {
        StringBuilder res = new StringBuilder ( );
        res.append ( String.format ( "Array:size=%d,capacity=%d\n" , size , data.length ) );
        res.append ( '[' );
        for ( int i = 0 ; i < size ; i++ ) {
            res.append ( data[ i ] );
            if ( i != size - 1 )
                res.append ( ',' );
        }
        res.append ( ']' );
        return res.toString ( );
    }

    /**
     * 获取index索引位置的元素。对data进行了一个隐藏
     *
     * @param index
     * @return
     */
    public E get ( int index ) {
        if ( index < 0 || index >= size )
            throw new IllegalArgumentException ( "get failed index is illegal" );
        return data[ index ];
    }

    /**
     * 获取最后一个元素
     *
     * @return
     */
    public E getLast ( ) {
        return get ( size - 1 );
    }

    /**
     * 获取第一个元素
     *
     * @return
     */
    public E getFirst ( ) {
        return get ( 0 );
    }

    /**
     * set方法。
     *
     * @param index
     * @param e
     * @return
     */
    public void set ( int index , E e ) {
        if ( index < 0 || index >= size )
            throw new IllegalArgumentException ( "get failed index is illegal" );
        data[ index ] = e;
    }

    /**
     * 实现了容量的扩充
     *
     * @param newCapacity
     */
    private void resize ( int newCapacity ) {
        E[] newData = ( E[] ) new Object[ newCapacity ];
        for ( int i = 0 ; i < size ; i++ ) {
            newData[ i ] = data[ i ];
        }
        data = newData;
    }
}
